<template>
  <div class="app-container">
    <!-- ====== 搜索区（不改功能与字段） ====== -->
    <el-form
      :model="queryParams"
      ref="queryRef"
      :inline="true"
      v-show="showSearch"
      label-width="68px"
      class="search-bar"
    >
      <el-form-item label="工单编号" prop="woCode">
        <el-input
          v-model="queryParams.woCode"
          placeholder="请输入工单编号"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="工单标题" prop="title">
        <el-input
          v-model="queryParams.title"
          placeholder="请输入工单标题"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="紧急程度" prop="urgency">
        <el-input
          v-model="queryParams.urgency"
          placeholder="请输入紧急程度"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <!-- <el-form-item label="设备名称" prop="equipmentId">
        <el-input v-model="queryParams.equipmentId" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
      </el-form-item> -->

      <!-- <el-form-item label="故障时间" prop="submitTime">
        <el-date-picker clearable v-model="queryParams.submitTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择故障时间"/>
      </el-form-item>   -->

      <el-form-item label="故障类型" prop="status">
        <el-select
          v-model.number="queryParams.faultType"
          placeholder="故障类型"
          clearable
        >
          <el-option
            v-for="dict in order_fault_type"
            :key="dict.value"
            :label="dict.label"
            :value="Number(dict.value)"
          />
        </el-select>
      </el-form-item>

      <el-form-item class="search-actions">
        <el-button type="primary" icon="Search" @click="handleQuery"
          >搜索</el-button
        >
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <!-- ====== 工具栏 ====== -->
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['sbtz:order:add']"
          >新增</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['sbtz:order:edit']"
          >修改</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['sbtz:order:remove']"
          >删除</el-button
        >
      </el-col>
      <el-col :span="1.5"></el-col>
      <right-toolbar
        v-model:showSearch="showSearch"
        @queryTable="getList"
      ></right-toolbar>
    </el-row>

    <!-- ====== 列表 ====== -->
    <el-table
      v-loading="loading"
      :data="orderList"
      border
      stripe
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="55" align="center" />
      <!-- <el-table-column type="expand" width="44">
        <template #default="{ row }">
          <div v-if="hasAny(row)" class="info-grid" :class="gridClass(row)">
            <section v-if="hasAttachments(row)" class="info-card">
              <header class="info-card__title"></header>
              <AttachmentList
                :attachments="row.attachments"
                :orderId="row.id"
                compact
              />
            </section>

            <section v-if="hasNode(row)" class="info-card">
              <header class="info-card__title"><span>设备信息</span></header>
              <el-descriptions class="kv" :column="2" size="small">
                <el-descriptions-item label="名称">{{
                  row.node?.name || "-"
                }}</el-descriptions-item>
                <el-descriptions-item label="编码">{{
                  row.node?.code || "-"
                }}</el-descriptions-item>
                <el-descriptions-item label="型号">{{
                  row.node?.model || "-"
                }}</el-descriptions-item>
                <el-descriptions-item label="规格">{{
                  row.node?.specification || "-"
                }}</el-descriptions-item>
                <el-descriptions-item label="品牌">{{
                  row.node?.brand || "-"
                }}</el-descriptions-item>
              </el-descriptions>
            </section>

            <section v-if="hasSpare(row)" class="info-card">
              <header class="info-card__title"><span>备件明细</span></header>
              <el-table
                :data="row.spareInfos || []"
                size="small"
                stripe
                border="{false}"
                class="spare-table"
              >
                <el-table-column prop="code" label="编号" width="140" />
                <el-table-column prop="name" label="名称" min-width="160" />
                <el-table-column prop="qty" label="数量" width="90">
                  <template #default="{ row }"
                    ><el-tag type="success" effect="light">{{
                      row.qty
                    }}</el-tag></template
                  >
                </el-table-column>
                <el-table-column
                  prop="stockAvailable"
                  label="可用"
                  width="90"
                />
                <el-table-column prop="stockTotal" label="总量" width="90" />
              </el-table>
            </section>
          </div>
          <el-empty v-else description="无附件 / 备件 / 设备信息" />
        </template>
      </el-table-column> -->

      <el-table-column label="工单ID" align="center" prop="id" />
      <el-table-column label="工单编号" align="center" prop="woCode" />
      <el-table-column label="工单标题" align="center" prop="title" />
      <el-table-column label="工单类型" align="center" prop="orderType" />
      <el-table-column label="紧急程度" align="center" prop="urgency" />
      <el-table-column label="设备名称" align="center" prop="equipmentId" />
      <el-table-column
        label="故障/需求描述"
        align="center"
        prop="faultDesc"
        show-overflow-tooltip
      />
      <el-table-column label="报修人" align="center" prop="requesterId" />
      <el-table-column label="派单人" align="center" prop="dispatcherId" />
      <el-table-column label="接修人" align="center" prop="receiverId" />
      <el-table-column label="工单状态" align="center" prop="status" />
      <el-table-column label="工单来源" align="center" prop="source" />
      <el-table-column
        label="需求报送时间"
        align="center"
        prop="submitTime"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.submitTime, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column>
      <el-table-column
        label="工单创建时间"
        align="center"
        prop="createdTime"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.createdTime, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column>
      <el-table-column
        label="计划开始时间"
        align="center"
        prop="planStartTime"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.planStartTime, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column>
      <el-table-column
        label="计划完成时间"
        align="center"
        prop="planEndTime"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.planEndTime, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column>
      <!-- <el-table-column
        label="实际开始时间"
        align="center"
        prop="actualStartTime"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.actualStartTime, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column>
      <el-table-column
        label="实际完成时间"
        align="center"
        prop="actualEndTime"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.actualEndTime, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column> -->

      <!-- 实际开始时间 -->
<el-table-column label="实际开始时间" align="center" prop="actualStartTime" width="180">
  <template #default="scope">
    <span>{{ parseTime(scope.row.actualStartTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
  </template>
</el-table-column>

<!-- 实际完成时间 -->
<el-table-column label="实际完成时间" align="center" prop="actualEndTime" width="180">
  <template #default="scope">
    <span>{{ parseTime(scope.row.actualEndTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
  </template>
</el-table-column>

      <el-table-column label="备注说明" align="center" prop="remark" />
      <el-table-column
        label="更新时间"
        align="center"
        prop="updatedAt"
        width="180"
      >
        <template #default="scope"
          ><span>{{
            parseTime(scope.row.updatedAt, "{y}-{m}-{d}")
          }}</span></template
        >
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        class-name="small-padding fixed-width"
      >
        <template #default="scope">
          <el-button
            link
            type="primary"
            icon="Edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['sbtz:order:edit']"
            >修改</el-button
          >
          <el-button
            link
            type="primary"
            icon="Delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['sbtz:order:remove']"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- ====== 新增/修改对话框（仅样式分块，字段与逻辑不变） ====== -->
    <el-dialog
      :title="title"
      v-model="open"
      width="90%"
      class="order-dialog dlg-fixed-footer"
      append-to-body
      destroy-on-close
    >
      <el-form
        ref="orderRef"
        :model="form"
        :rules="rules"
        label-width="110px"
        class="order-form"
      >
        <!-- 🟩 基础信息 -->
        <section class="form-block">
          <div class="block-head theme-basic">
            <span class="head-dot"></span>
            <span class="head-text">基础信息</span>
          </div>
          <div class="block-body">
            <el-row :gutter="16">
              <el-col :span="6">
                <el-form-item label="工单编号" prop="woCode">
                  <el-input
                    v-model="form.woCode"
                    placeholder="请输入工单编号"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="工单标题" prop="title">
                  <el-input v-model="form.title" placeholder="请输入工单标题" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="工单状态">
                  <el-select
                    v-model="form.status"
                    placeholder="请选择工单状态"
                    clearable
                  >
                    <el-option label="提交" value="DRAFT" />
                    <el-option label="已派工" value="DISPATCHED" />
                    <el-option label="进行中" value="IN_PROGRESS" />
                    <el-option label="挂起/暂停" value="SUSPENDED" />
                    <el-option label="已完成" value="DONE" />
                    <el-option label="已取消" value="CANCELLED" />
                  </el-select>
                </el-form-item> 
              </el-col>
              <el-col :span="6" v-if="form.status == 'DONE'">
                <el-button type="primary" @click="openDialog">新增采集数据</el-button>
                <CollectDataDialog ref="dialog" @confirm="handleConfirm" />
              </el-col>
              <el-col :span="24"></el-col>
              <el-col :span="6">
                <el-form-item label="紧急程度" prop="urgency">
                  <el-input
                    v-model="form.urgency"
                    placeholder="请输入紧急程度"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="维护类型">
                  <el-select
                    v-model="form.source"
                    placeholder="请选择维护类型"
                    clearable
                  >
                    <el-option label="手工" value="MANUAL" />
                    <el-option label="预测性自动" value="AUTO_PREDICT" />
                    <el-option label="预防性自动" value="AUTO_PM" />
                  </el-select>
                </el-form-item>
              </el-col>

              <!-- 你的故障类型字段保持不变 -->
              <el-col :span="6">
                <el-form-item label="故障类型" prop="status">
                  <el-select
                    v-model.number="form.faultType"
                    placeholder="故障类型"
                  >
                    <el-option
                      v-for="dict in order_fault_type"
                      :key="dict.value"
                      :label="dict.label"
                      :value="Number(dict.value)"
                    />
                  </el-select>
                </el-form-item>
              </el-col>

              <el-col :span="6"> 
                <el-form-item label="故障时间" prop="submitTime">
                  <el-date-picker
                    v-model="form.submitTime"
                    type="datetime"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    clearable
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="报修人" prop="requesterId">
                  <el-input
                    v-model="form.requesterId"
                    placeholder="请输入报修人"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="24">
                <el-form-item label="故障现象" prop="faultDesc" class="w-full">
              <el-input
                v-model="form.faultDesc"
                type="textarea"
                placeholder="请描述故障现象"
                :rows="3"
              />
            </el-form-item>
              </el-col>
              


            </el-row>
          </div>
        </section>

        <!-- 🟦 设备与备件 -->
        <section class="form-block">
          <div class="block-head theme-asset">
            <span class="head-dot"></span>
            <span class="head-text">设备与备件</span>
          </div>
          <div class="block-body">
            <el-form-item label="设备名称" prop="equipmentId" class="w-full">
              <el-cascader
                v-model="rootPath"
                :props="cProps"
                clearable
                filterable
                placeholder="请选择设备路径"
                style="min-width: 360px"
                show-all-levels
              >
                <template #default="{ node, data }">
                  <div class="cas-opt">
                    <span class="cas-label" :title="data.label">{{
                      data.label
                    }}</span>
                    <el-tag
                      v-if="typeLabelOf(node, data)"
                      size="small"
                      :type="typeTagType(typeLabelOf(node, data))"
                      effect="light"
                      class="cas-badge"
                    >
                      {{ typeLabelOf(node, data) }}
                    </el-tag>
                  </div>
                </template>
                <template #tag="{ node, data }">
                  <span class="sel-tag">
                    {{ data.label }}
                    <span class="sel-type" v-if="typeLabelOf(node, data)"
                      >（{{ typeLabelOf(node, data) }}）</span
                    >
                  </span>
                </template>
              </el-cascader>
            </el-form-item>

            <SparePickerPlus
              ref="spareRef"
              v-model:specialItems="form.specialItems"
              :tableHeight="180"
              selectWidth="360px"
            />
          </div>
        </section>

        <!-- 🟨 人员与时间 -->
        <section class="form-block">
          <div class="block-head theme-time">
            <span class="head-dot"></span>
            <span class="head-text">人员与时间</span>
          </div>
          <div class="block-body">
            <el-row :gutter="16">
              

              <el-col :span="8">
                <el-form-item label="计划开始时间" prop="planStartTime">
                  <el-date-picker
                    v-model="form.planStartTime"
                    type="date"
                    value-format="YYYY-MM-DD"
                    clearable
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <el-form-item label="计划完成时间" prop="planEndTime">
                  <el-date-picker
                    v-model="form.planEndTime"
                    type="date"
                    value-format="YYYY-MM-DD"
                    clearable
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <el-form-item label="派单人" prop="dispatcherId">
                  <el-input
                    v-model="form.dispatcherId"
                    placeholder="请输入派单人"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <!-- <el-form-item label="实际开始时间" prop="actualStartTime">
          <el-date-picker v-model="form.actualStartTime" type="date" value-format="YYYY-MM-DD" clearable style="width:100%" />
        </el-form-item> -->
                <el-form-item label="实际开始时间" prop="actualStartTime">
                  <el-date-picker
                    v-model="form.actualStartTime"
                    type="datetime"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    clearable
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <!-- <el-form-item label="实际完成时间" prop="actualEndTime">
          <el-date-picker v-model="form.actualEndTime" type="date" value-format="YYYY-MM-DD" clearable style="width:100%" />
        </el-form-item> -->
                <el-form-item label="实际完成时间" prop="actualEndTime">
                  <el-date-picker
                    v-model="form.actualEndTime"
                    type="datetime"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    clearable
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>

              <el-col :span="8">
                <el-form-item label="接修人" prop="receiverId">
                  <el-input
                    v-model="form.receiverId"
                    placeholder="请输入接修人"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </div>
        </section>

        <!-- 🟪 附件与备注 -->
        <section class="form-block">
          <div class="block-head theme-attach">
            <span class="head-dot"></span>
            <span class="head-text">附件与备注</span>
          </div>
          <div class="block-body">
            <el-form-item label="上传附件" class="w-full">
              <AttachmentsUploader
                ref="attRef"
                :entity-id="form.id"
                :list-fn="listAttachments"
                :upload-fn="uploadAttachments"
                :delete-fn="delAttachments"
                accept=".png,.jpg,.jpeg,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar"
                list-type="picture-card"
                :multiple="true"
                :auto-fetch="true"
              />
            </el-form-item>

            <el-form-item label="备注说明" prop="remark" class="w-full">
              <el-input
                v-model="form.remark"
                type="textarea"
                placeholder="请输入备注"
                :rows="3"
              />
            </el-form-item>
          </div>
        </section>
      </el-form>

      <!-- 底部按钮：始终可见 -->
      <template #footer>
        <div class="dialog-footer sticky-footer">
          <el-button @click="cancel">取 消</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>          
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Order">
import {
  ref,
  reactive,
  computed,
  toRefs,
  getCurrentInstance,
  nextTick,
} from "vue";
import {
  listOrder,
  getOrder,
  delOrder,
  addOrder,
  updateOrder,
} from "@/api/sbtz/order";
import {
  listAttachments,
  uploadAttachments,
  delAttachments,
} from "@/api/sbtz/attachment";
import { UploadFilled } from "@element-plus/icons-vue";
import { listSpare } from "@/api/sbtz/spare";
import SparePickerOrder from "@/components/sbtz/spare/SparePickerOrder.vue";
import SparePickerPlus from "@/components/sbtz/spare/SparePickerPlus.vue";

import SparePicker from "@/components/sbtz/spare/SparePicker.vue";
import AttachmentsUploader from "@/components/sbtz/file/AttachmentsUploader.vue";
import AttachmentList from "@/components/sbtz/file/AttachmentList.vue";
import { cascaderChildren, getLeafNodePath } from "@/api/sbtz/sbtz";

const uploadRef = ref();
const dirPickerRef = ref();
const rootPath = ref([]); // 例如选择后变成 [系统id, 母设备id, 子设备id]

// 已有附件（仅用于表格展示）
const existingAttachments = ref([]);

import CollectDataDialog from "@/components/sbtz/order/CollectDataDialog.vue";

const dialog = ref();

function openDialog() {
  dialog.value.open();
}

function handleConfirm(data) {
  console.log("采集数据：", data);
  // 可直接提交后端或存入父组件变量
}

// 「服务器已有的文件」与「本次新增待上传」分离管理
const serverFileList = ref([]); // [{ name,url,status,size,uid,id,isServer,relativePath }]
const pendingFileList = ref([]); // el-upload 产生的本地文件对象（含 raw）
const mergedFileList = computed(() => [
  ...serverFileList.value,
  ...pendingFileList.value,
]);

const { proxy } = getCurrentInstance();
const { order_fault_type } = proxy.useDict("order_fault_type");

const orderList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const cascaderKey = ref(0);
const showCascader = ref(true);
const spareRef = ref(null);

// 后端 code -> 中文名
const TYPE_LABELS = {
  SYSTEM: "系统",
  MACHINE: "母设备",
  MODULE: "子设备",
  COMPONENT: "部件",
  PART: "零件",
};

const hasAttachments = (row) =>
  Array.isArray(row.attachments) && row.attachments.length > 0;
const hasSpare = (row) =>
  Array.isArray(row.spareInfos) && row.spareInfos.length > 0;
const hasNode = (row) =>
  !!(row.node && (row.node.name || row.node.code || row.node.model));
const hasAny = (row) => hasAttachments(row) || hasSpare(row) || hasNode(row);
const gridClass = (row) => {
  let c = 0;
  if (hasAttachments(row)) c++;
  if (hasNode(row)) c++;
  if (hasSpare(row)) c++;
  return `cols${Math.max(c, 1)}`;
};

async function loadSpareOptions() {
  const res = await listSpare({ pageNum: 1, pageSize: 9999 });
  const rows = res?.rows ?? res?.data?.rows ?? res?.data ?? [];
  return rows; // 组件会用 optionValueKey/optionLabelKey 做归一化
}

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    woCode: null,
    title: null,
    orderType: null,
    urgency: null,
    equipmentId: null,
    faultDesc: null,
    requesterId: null,
    dispatcherId: null,
    receiverId: null,
    status: null,
    source: null,
    submitTime: null,
    planStartTime: null,
    planEndTime: null,
    actualStartTime: null,
    actualEndTime: null,
    updatedAt: null,
    faultType: null,
    spares: [], // [{spareId, qty}]
  },
  rules: {
    woCode: [{ required: true, message: "工单编号不能为空", trigger: "blur" }],
    // 保留你的可选校验（注释）
  },
});

const { queryParams, form, rules } = toRefs(data);

form.value.equipmentId = computed(() =>
  Array.isArray(rootPath.value) && rootPath.value.length
    ? rootPath.value[rootPath.value.length - 1]
    : 0
);

/** 查询工单列表列表 */
function getList() {
  loading.value = true;
  listOrder(queryParams.value).then((response) => {
    orderList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

function typeTagType(label) {
  const map = {
    系统: "success",
    母设备: "primary",
    子设备: "warning",
    部件: "warning",
    零件: "info",
  };
  return map[label] || "info";
}

/**
 * 从后端返回的 data.nodeType 读取类型中文名；
 * 若没有（极端兜底），按层级 node.level 粗略推断。
 */
function typeLabelOf(node, data) {
  const code = data && (data.nodeType || data.node_type);
  if (code && TYPE_LABELS[code]) return TYPE_LABELS[code];

  // —— 兜底：根据级联层级推断（后端没给 nodeType 时才会走到这）——
  // level: 1=系统/根；2=母设备；3=子设备；4=部件；5+=零件
  const lv = node && typeof node.level === "number" ? node.level : 0;
  if (lv <= 1) return "系统";
  if (lv === 2) return "母设备";
  if (lv === 3) return "子设备";
  if (lv === 4) return "部件";
  return "零件";
}

// ✅ 让 v-model 返回“单个 id”，而不是路径数组
const cProps = {
  checkStrictly: true,
  emitPath: true,
  value: "id",
  label: "label",
  // children: 'children',  // ❌ 懒加载不需要
  lazy: true,
  lazyLoad: (node, resolve) => {
    const parentId = node.level === 0 ? 0 : node.value;
    cascaderChildren(parentId)
      .then((res) => resolve(res?.data || [])) // 需要后端返回 {id,label,leaf,nodeType}
      .catch(() => resolve([]));
  },
};

// ✅ 只在“收起”时重建组件，清掉面板展开/加载缓存；“打开”不动 v-model
function onCascaderVisible(visible) {
  if (!visible) hardResetCascader();
}

function hardResetCascader() {
  showCascader.value = false;
  nextTick(() => {
    cascaderKey.value += 1;
    showCascader.value = true;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置（同时清理附件缓存）
function reset() {
  form.value = {
    id: null,
    woCode: null,
    title: null,
    orderType: null,
    urgency: null,
    equipmentId: null,
    faultDesc: null,
    requesterId: null,
    dispatcherId: null,
    receiverId: null,
    status: null,
    source: null,
    submitTime: null,
    planStartTime: null,
    planEndTime: null,
    actualStartTime: null,
    actualEndTime: null,
    priorityScore: null,
    remark: null,
    updatedAt: null,
    /** ✅ 新增以下几个关键字段 */
    needSpare: 0,
    faultType: 1,
    spares: [],
    specialItems: [],
  };
  serverFileList.value = [];
  pendingFileList.value = [];
  existingAttachments.value = [];
  proxy.resetForm("orderRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map((item) => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  rootPath.value = [];
  title.value = "添加工单列表";
}

/** 修改按钮操作（关键：nextTick 后回显附件到 el-upload） */
async function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value;
  const response = await getOrder(_id);
  form.value = response.data || {};

  const path = await getLeafNodePath(form.value.equipmentId);
  const idPath = (path?.data || path)?.map((x) => x.id) || [];

  // 2) 逐级预加载级联每层 children（保证可回显）
  for (let i = 0; i < idPath.length; i++) {
    const parentId = i === 0 ? 0 : idPath[i - 1];
    await cascaderChildren(parentId); // 触发后端懒加载缓存（若你本地要存的话）
  }
  // 3) 设置 v-model
  rootPath.value = idPath;
  open.value = true;
  title.value = "修改工单列表";

  await nextTick();

  const infos = Array.isArray(form.value.spareInfos)
    ? form.value.spareInfos
    : [];
  form.value.specialItems = infos.map((it) => ({
    spareId: it.spareId, // 如果后端查得到
    code: it.code || "",
    name: it.name || "",
    type: Number(it.type) || 0,
    qty: it.qty || 1,
    orderDate: Number(it.orderDate || 0),
    stockAvailable: Number(it.stockAvailable ?? 0),
  }));

  // ✅ 确保字段不为 null
  if (!Array.isArray(form.value.specialItems)) form.value.specialItems = [];

  // ✅ 同步 SparePickerOrder 内部状态
  await nextTick(() => {
    spareRef.value?.getValue?.();
  });

  // ✅ 刷新附件列表
  await refreshAttachments(form.value.id);
}

/** 提交按钮 */
const submitting = ref(false);
const attRef = ref(null);

async function submitForm() {
  if (submitting.value) return;
  submitting.value = true;
  try {
    await proxy.$refs["orderRef"]?.validate();

    /** ✅ 校验备件清单 */
    const valid = spareRef.value?.validate?.();
    if (valid === false) return;

    const model = form.value;

    const startParentId =
      Array.isArray(rootPath?.value) && rootPath.value.length
        ? rootPath.value[rootPath.value.length - 1]
        : 0;
    model.equipmentId = startParentId;
    model.assetId = startParentId;

    // ✅ 把 assetId 写到每条 specialItems 里（如果已有就保留原值）
    const specialItemsWithAsset = (model.specialItems || []).map((it) => ({
      ...it,
      assetId: it?.assetId ?? startParentId,
    }));

    const payload = {
      ...model,
      specialItems: specialItemsWithAsset,
    };

    if (model.id) {
      await updateOrder(payload);
      proxy.$modal.msgSuccess("修改成功");
    } else {
      const resp = await addOrder(payload);
      model.id = resp?.data?.id ?? resp?.id;
      proxy.$modal.msgSuccess("新增成功");
    }

    /** 上传附件 */
    if (attRef.value) {
      const { uploaded } = await attRef.value.uploadAll(model.id);
      if (uploaded > 0) proxy.$modal.msgSuccess("附件上传成功");
    }

    open.value = false;
    getList();
  } finally {
    submitting.value = false;
  }
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal
    .confirm('是否确认删除工单列表编号为"' + _ids + '"的数据项？')
    .then(function () {
      return delOrder(_ids);
    })
    .then(() => {
      getList();
      proxy.$modal.msgSuccess("删除成功");
    })
    .catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download(
    "sbtz/order/export",
    {
      ...queryParams.value,
    },
    `order_${new Date().getTime()}.xlsx`
  );
}

function handleExportFull() {
  proxy.download(
    "/sbtz/order/exportFull",
    { ...queryParams.value },
    `order_full_${Date.now()}.xlsx`
  );
}

function handleExportFullXlsx() {
  // 你们的封装如果默认 POST，这里后端已支持 GET/POST 都行
  proxy.download(
    "/sbtz/order/exportFullXlsx",
    { ...queryParams.value },
    `order_full_${Date.now()}.xlsx`
  );
}

/** el-upload：占位 http-request（我们统一在提交时上传） */
const noop = () => {};

/** el-upload：选择文件变化（包含服务器已有 + 新增）→ 仅保留“非服务器”的部分作为待上传 */
function onUploadChange(uploadFile, uploadFiles) {
  pendingFileList.value = (uploadFiles || []).filter((f) => !f.isServer);
}

/** el-upload：移除文件（区分服务器已有/本次新增） */
async function onUploadRemove(file, uploadFiles) {
  if (file.isServer) {
    await delAttachments(file.id);
    serverFileList.value = serverFileList.value.filter(
      (f) => f.uid !== file.uid
    );
    proxy.$modal.msgSuccess("已删除附件");
    // 同步表格
    existingAttachments.value = existingAttachments.value.filter(
      (x) => x.id !== file.id
    );
  } else {
    pendingFileList.value = pendingFileList.value.filter(
      (f) => f.uid !== file.uid
    );
  }
}

/** 选择文件夹（保持你的功能） */
function pickDirectory() {
  dirPickerRef.value && dirPickerRef.value.click();
}

/** 文件夹选择（保持你的功能，但落到 pendingFileList） */
function onDirectoryPicked(e) {
  const files = Array.from(e.target.files || []);
  const toPush = files.map((raw, idx) => ({
    name: raw.name,
    status: "ready",
    size: raw.size,
    raw,
    uid: `${Date.now()}_${idx}`,
    relativePath: raw.webkitRelativePath || "",
  }));
  pendingFileList.value = pendingFileList.value.concat(toPush);
  e.target.value = "";
}

/** 上传前校验（保持你的逻辑） */
function beforeUpload(file) {
  const isLt100M = file.size / 1024 / 1024 < 100;
  if (!isLt100M) {
    proxy.$modal.msgError(`文件 ${file.name} 超过 100MB`);
    return false;
  }
  return true;
}

/** el-upload/表格：预览（保持你的逻辑） */
function onPreview(file) {
  const url = file.url || file.raw?.url;
  if (!url) return;
  window.open(url, "_blank");
}
function previewAttachment(row) {
  window.open(makeAbsUrl(row.fileUrl), "_blank");
}

/** 表格：删除已有附件（保持你的功能，同时刷新回显） */
async function removeAttachment(row) {
  await delAttachments(row.id);
  proxy.$modal.msgSuccess("删除成功");
  await refreshAttachments(form.value.id);
}

/** 拉取并回显服务器附件（关键：将返回数据映射到 el-upload 的 file 结构） */
async function refreshAttachments(orderId) {
  if (!orderId) return;
  const resp = await listAttachments(orderId);
  const list = resp?.rows || resp?.data || resp || [];

  // 表格数据（保持你的功能）
  existingAttachments.value = list;

  // 映射成 el-upload file 结构（带完整 URL）
  serverFileList.value = list.map((a) => ({
    name: a.fileName,
    url: makeAbsUrl(a.fileUrl),
    status: "success",
    size: a.fileSize,
    uid: `server_${a.id}`,
    id: a.id,
    isServer: true,
    relativePath: a.relativePath || "",
  }));
}

/** 将可能的相对路径转换为可访问的绝对 URL */
function makeAbsUrl(path) {
  if (!path) return "";
  if (/^https?:\/\//i.test(path)) return path;
  // 兼容 RuoYi：VITE_APP_BASE_API / VUE_APP_BASE_API 作为前缀
  const BASE =
    import.meta.env?.VITE_APP_BASE_API || process.env?.VUE_APP_BASE_API || "";
  return `${BASE}${path}`;
}
onMounted(loadSpareOptions);

getList();
</script>
<style scoped>
/* —— Dialog：高度、滚动、底部固定 —— */
:deep(.order-dialog .el-dialog) {
  display: flex;
  flex-direction: column;
  height: 84vh; /* 视窗高度 */
  max-height: 90vh;
}
:deep(.order-dialog .el-dialog__header) {
  padding: 12px 16px;
  border-bottom: 1px solid #eef0f4;
}
:deep(.order-dialog .el-dialog__body) {
  flex: 1;
  overflow: auto;
  padding: 12px 14px 0;
  background: #f5f7fb;
}
:deep(.order-dialog .el-dialog__footer) {
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: #fff;
  border-top: 1px solid #e9edf3;
  padding: 10px 16px;
  box-shadow: 0 -8px 18px -14px rgba(15, 23, 42, 0.25);
}

/* —— 分块卡片 —— */
.form-block {
  background: #fff;
  border: 1px solid #e6ebf2;
  border-radius: 12px;
  overflow: hidden;
  margin: 12px 0;
  box-shadow: 0 6px 20px -16px rgba(15, 23, 42, 0.35);
}

/* —— 分块标题条（更醒目） —— */
.block-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  font-weight: 700;
  color: #0f1950;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.block-head .head-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #0f1950;
  opacity: 0.25;
}

/* 主题色：基础/设备/时间/附件 */
/* .theme-basic  { background: linear-gradient(90deg,#eaf2ff,#ffffff); border-bottom-color:#d6e4ff; }
.theme-asset  { background: linear-gradient(90deg,#eafaf3,#ffffff); border-bottom-color:#cfeee0; }
.theme-time   { background: linear-gradient(90deg,#fff5e6,#ffffff); border-bottom-color:#ffe2b8; }
.theme-attach { background: linear-gradient(90deg,#f5efff,#ffffff); border-bottom-color:#e5d9ff; } */
.theme-basic {
  background: linear-gradient(90deg, #eafaf3, #ffffff);
  border-bottom-color: #cfeee0;
}
.theme-asset {
  background: linear-gradient(90deg, #eafaf3, #ffffff);
  border-bottom-color: #cfeee0;
}
.theme-time {
  background: linear-gradient(90deg, #eafaf3, #ffffff);
  border-bottom-color: #cfeee0;
}
.theme-attach {
  background: linear-gradient(90deg, #eafaf3, #ffffff);
  border-bottom-color: #cfeee0;
}

.block-body {
  padding: 14px 16px 4px;
}

/* —— 表单控件宽度与间距 —— */
.el-form-item {
  margin-bottom: 12px;
}
.el-input,
.el-select,
.el-date-picker,
:deep(.el-cascader) {
  width: 100%;
}
.w-full {
  width: 100%;
}

/* —— 级联下拉里的行样式 —— */
.cas-opt {
  display: flex;
  align-items: center;
  gap: 6px;
}
.cas-label {
  max-width: 360px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cas-badge {
  margin-left: auto;
}

/* —— 列表卡片（保持你原有） —— */
.info-grid {
  display: grid;
  gap: 12px;
}
.info-grid.cols1 {
  grid-template-columns: 1fr;
}
.info-grid.cols2 {
  grid-template-columns: 1fr 1fr;
}
.info-grid.cols3 {
  grid-template-columns: 1fr 1fr 1fr;
}
.info-card {
  background: #fff;
  border: 1px solid #eef0f4;
  border-radius: 10px;
  padding: 10px 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.03);
}
.info-card__title {
  font-weight: 600;
  color: #334155;
  margin-bottom: 8px;
}

/* —— 搜索区轻卡片 —— */
.search-bar {
  background: #fff;
  padding: 12px 12px 2px;
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}

/* —— 底部按钮（兜底） —— */
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
</style>
